package com.yeh.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.yeh.dao.BaseDao;

/**
 * 
 * <p>Title: BaseDaoImpl</p>
 * <p>Description: BeseDaoImpl</p>
 * <p>Company:  Co.</p>
 * <p>Package: com.yeh.dao.impl</p>
 * @author <a href="mailto:yehshuai@126.com">叶帅</a>  
 * <p>DateTime: 2015年9月8日 ★  下午2:47:04</p> 
 * @Version V1.0.0
 */
@Repository
public class BaseDaoImpl<T ,PK extends Serializable> implements BaseDao<T,PK> {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	/** The entity class. */
    private final Class<T> entityClass;
    
    /** The session factory. */
    @Autowired(required = true)
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    /**
     * Instantiates a new base dao impl.
     */
    @SuppressWarnings("unchecked")
	protected BaseDaoImpl() {
        //this.entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getClass();
    	Type type = getClass().getGenericSuperclass(); 
    	if (type instanceof ParameterizedType) {
    		Type typetrue = ((ParameterizedType) type).getActualTypeArguments()[0];
            this.entityClass = (Class<T>)typetrue;
    	}else{
    		this.entityClass =(Class<T>)type.getClass();
    	}
    }
	
    /**
     * Gets the session.
     *
     * @return the session
     */
    public Session getSession(){
        Session session = null;
        try{
            session = sessionFactory.getCurrentSession();
        }catch (HibernateException e){
            e.printStackTrace();
            session =sessionFactory.openSession();
        }
        return session;
    }

    /**
     * Open session.
     *
     * @return the session
     */
    public Session openSession(){
        return sessionFactory.openSession();
    }

    @Override
	@SuppressWarnings("unchecked")
	public T get(PK refcode) {
		Assert.notNull(refcode, "refcode is required");
	    return (T)getSession().get(this.entityClass, refcode);
	}

	@Override
	@SuppressWarnings("unchecked")
	public T get(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
	    Assert.notNull(value, "value is required");
	    String hql = "from " + this.entityClass.getName() + " as model where model." + propertyName + " = :propertyName";
	    return (T) getSession().createQuery(hql).setParameter("propertyName", value).uniqueResult();
	}

	@Override
	@SuppressWarnings("unchecked")
	public T get(Map<String, Object> propertyMap) {
		Criteria crit = getSession().createCriteria(this.entityClass);
	    crit.add(Restrictions.allEq(propertyMap));
	    return (T) crit.uniqueResult();
	}
	@Override
	@SuppressWarnings("unchecked")
	public List<T> getList(){
		String hql = "from " + this.entityClass.getName();
		return getSession().createQuery(hql).list();
	}
	
	@Override
	public List<T> getList(PK[] arrayPks) {
		List<T> c_list = new ArrayList<T>();
		for (int i = 0; i < arrayPks.length; i++) {
			c_list.add(get(arrayPks[i]));
		}
		return c_list;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> getList(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
	    Assert.notNull(value, "value is required");
	    String hql = "from " + this.entityClass.getName() + " as model where model." + propertyName + " = :propertyName";
	    /*if ((StringUtils.isNotBlank(orderBy)) && (orderType != null)) {
	      if (orderType == Pager.OrderType.asc)
	        hql = hql + " order by model." + orderBy + " asc";
	      else {
	        hql = hql + " order by model." + orderBy + " desc";
	      }
	    }*/
	    return getSession().createQuery(hql).setParameter("propertyName", value).list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> getList(Map<String, Object> propertyMap) {
		Criteria criteria = getSession().createCriteria(this.entityClass);
	    criteria.add(Restrictions.allEq(propertyMap));
	    /*if ((StringUtils.isNotBlank(orderBy)) && (orderType != null)) {
	      if (orderType == Pager.OrderType.asc)
	        criteria.addOrder(Order.asc(orderBy));
	      else {
	        criteria.addOrder(Order.desc(orderBy));
	      }
	    }*/
	    return criteria.list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public PK save(T entity) {
		Assert.notNull(entity, "entity is required");
	    return (PK)getSession().save(entity);
	}

	@Override
	public void update(T entity) {
		Assert.notNull(entity, "entity is required");
	    getSession().update(entity);
	}

	@Override
	public void delete(T entity) {
		Assert.notNull(entity, "entity is required");
	    getSession().delete(entity);
	}

	@Override
	public void delete(PK refcode) {
		Assert.notNull(refcode, "refcode is required");
	    Object entity = get(refcode);
	    getSession().delete(entity);
	}

	@Override
	public void delete(PK[] refcodes) {
		Assert.notEmpty(refcodes, "refcodes must not be empty");
		for (PK refcode : refcodes) {
			Object entity = get(refcode);
			getSession().delete(entity);
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public void delete(String propertyName, Object value) {
		List<T> list = getList(propertyName, value);
	    if (list != null){
	    	for (Object entity : list){
	    		delete((T)entity);
	    	}
	    }
	}

	@Override
	@SuppressWarnings("unchecked")
	public void delete(Map<String, Object> propertyMap) {
		List<T> list = getList(propertyMap);
	    if (list != null){
	    	for (Object entity : list){
	    		delete((T)entity);
	    	}
	    }
	}

	@Override
	public Long getTotalCount() {
		String hql = "select count(*) from " + this.entityClass.getName();
	    return (Long)getSession().createQuery(hql).uniqueResult();
	}

	@Override
	public boolean isExist(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
	    Assert.notNull(value, "value is required");
	    List<T> objectList = getList(propertyName, value);
	    return (objectList != null) && (objectList.size() > 0);
	}

	@Override
	public boolean isExist(Map<String, Object> paramMap) {
		List<T> objectList = getList(paramMap);
	    return (objectList != null) && (objectList.size() > 0);
	}

	@Override
	public void flush() {
		getSession().flush();
	}

	@Override
	public void clear() {
		getSession().clear();
	}

	@Override
	public void evict(Object paramObject) {
		Assert.notNull(paramObject, "paramObject is required");
	    getSession().evict(paramObject);
	}



    
	

}
